﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NCM_MSTest.Alg
{
    internal class Error_DataProcess
    {
        /// <summary>
        /// 算术平均值
        /// </summary>
        /// <param name="x_0"></param>
        /// <param name="xs"></param>
        /// <returns></returns>
        public static double X_Ba(double x_0, double[] xs)
        {
            var sum = xs[0];
            for (int i = 1; i < xs.Length; i++)
            {
                sum += xs[i];
            }
            return sum / xs.Length;
        }

        public static double Sigma(double x_0, double[] xs)
        {
            var sigmas = new double[xs.Length];
            var ret = 0d;
            for (int i = 0; i < xs.Length; i++)
            {
                sigmas[i] = xs[i] - x_0;
            }
            for (int i = 0; i < xs.Length; i++)
            {
                ret += Math.Pow(sigmas[i], i + 1) / (i + 1);
            }
            return Math.Sqrt(ret);
        }

        /// <summary>
        /// 测量值在x1~x2之间的概率
        /// </summary>
        /// <param name="x_0"></param>
        /// <param name="x1"></param>
        /// <param name="x2"></param>
        /// <param name="sigma"></param>
        /// <returns></returns>
        public static double P(double x_0, double x1, double x2, double sigma)
        {
            var intFunc = new Func<double, double>(x =>
            {
                var p = -0.5 * Math.Pow((x - x_0) / sigma, 2);
                return 1 / (sigma * Math.Sqrt(2 * Math.PI)) * Math.Pow(Math.E, p);
            });
            //TODO:积分initFunc，上下限：x1,x2

            return 0d;
        }

        /// <summary>
        /// 绝对误差
        /// </summary>
        /// <param name="xi"></param>
        /// <param name="x_0"></param>
        /// <param name="xs"></param>
        /// <returns></returns>
        public static double AbsError(double xi, double x_0, double[] xs)
        {
            return xi - X_Ba(x_0, xs);
        }

        public static double ReltiveError(double xi, double x_0, double[] xs)
        {
            var xb = X_Ba(x_0, xs);
            return (xi - xb) / xb;
        }

        public static double MSE(double x_0, double[] xs)
        {
            var xb = X_Ba(x_0, xs);
            var sum = 0d;
            for (var i = 0; i < xs.Length; i++)
            {
                sum += Math.Pow(xs[i] - xb, 2);
            }
            return sum / xs.Length;
        }

        public static double StdMSD(double x_0, double[] xs)
        {
            return Math.Sqrt(MSE(x_0, xs));
        }

        public static double MathAverage(double x_0, double[] xs)
        {
            var wi = new Func<double, double>(x => 1 / Math.Pow(x - x_0, 2));
            var sumWi = xs.Select(x => wi(x)).Sum();
            var sumWiXi = xs.Select(x => wi(x) * x).Sum();
            return sumWiXi / sumWi;
        }
    }
}
